package pers.cz.orm.dao;

import pers.cz.common.connect.IConnection;

import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: Jef-orm
 * @description: 可以复用statement的sql执行引擎
 * @author: Cheng Zhi
 * @create: 2023-09-18 10:34
 **/
public class ReuseSqlEngine extends BaseSqlEngine {

    private final Map<String, Statement> statementMap = new HashMap<>();

    ReuseSqlEngine(IConnection iConnection) {
        super(iConnection);
    }

    private void putStatement(String sql, Statement stmt) {
        statementMap.put(sql, stmt);
    }

    private Statement getStatement(String s) {
        return statementMap.get(s);
    }

    private boolean hasStatementFor(String sql) {
        try {
            Statement statement = statementMap.get(sql);
            return statement != null && !statement.getConnection().isClosed();
        } catch (SQLException e) {
            return false;
        }
    }

    @Override
    public <T> T singleExecuteQuery(String sql, Class<T> resultType) {
        return executeQuery(sql, resultType, null).get(0);
    }

    @Override
    public <T> List<T> executeQuery(String sql, Class<T> resultType, Map<Integer, Object> params) {
        ResultSet resultSet = null;
        try {
            if (hasStatementFor(sql)) {
                Statement statement = getStatement(sql);
                resultSet = statement.executeQuery(sql);
            } else {
                PreparedStatement preparedStatement = connection.prepareStatement(sql);
                resultSet = preparedStatement.executeQuery();
                putStatement(sql, preparedStatement);
            }

            return dealResultSet(resultSet, resultType);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (resultSet != null) {
                try {
                    connection.close();
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    public int execute(String sql, Map<Integer, Object> params) {

        try {
            int count = 0;
            if (hasStatementFor(sql)) {
                Statement statement = getStatement(sql);
                count = statement.executeUpdate(sql);
            } else {
                PreparedStatement preparedStatement = connection.prepareStatement(sql);
                count = preparedStatement.executeUpdate();
                putStatement(sql, preparedStatement);
            }

            return count;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return 0;
    }

    @Override
    public void batch(String sql, List<Map<Integer, Object>> lists) {

    }
}
